<template>
  <div>
    <component
      ref="formRef"
      :is="his ? 'el-form' : 'div'"
      :inline="inline"
      :model="formParam"
      :size="size"
      v-bind="formConfig"
    >
      <!-- 表单/搜索 -->
      <Form
        v-if="form"
        v-bind="$props"
        @query="query"
        @reset="reset"
        @changeValue="(data) => $emit('changeValue', data)"
      >
        <template v-for="(value, name) in $slots" #[name]="slotData">
          <slot v-bind="slotData || {}" :name="name" />
        </template>
      </Form>
      <!-- 搜索 -->
      <Search
        v-if="search"
        v-bind="$props"
        @query="query"
        @reset="reset"
        @changeValue="(data) => $emit('changeValue', data)"
      >
        <!-- 导出插槽 -->
        <template v-for="(value, name) in $slots" #[name]="slotData">
          <slot v-bind="slotData || {}" :name="name" />
        </template>
      </Search>
      <!-- 中间层：信息/按钮等 -->
      <slot v-bind="{ loading }" name="info" />
      <!-- 列表 -->
      <el-form-item
        v-if="table"
        style="width: 100%; margin: 0"
        class="table"
        :label="label"
      >
        <!-- 如果操作事件没有触发，使用v-on="$listeners" -->
        <el-table
          class="form-table"
          style="width: 100%"
          :size="size"
          :data="keys ? formParam[keys] : tableData.data"
          v-loading="loading"
          v-bind="$attrs"
        >
          <!-- 复选框 -->
          <el-table-column
            v-if="table.showSelect"
            :fixed="table.showFixed"
            type="selection"
            width="55px"
            align="center"
          />
          <!-- 序号 -->
          <el-table-column
            v-if="table.showIndex"
            :fixed="table.showFixed"
            type="index"
            label="序号"
            width="80px"
            align="center"
          ></el-table-column>
          <!-- 内容 -->
          <el-table-column
            v-for="item in table.propList"
            v-bind="item"
            :key="item.prop"
          >
            <!-- 需要被el-form包裹效验才可生效 -->
            <template
              v-if="item.type || item.slotForm || item.slotName || item.render"
              #default="{ row, $index: index }"
            >
              <template v-if="item.render && typeof item.render === 'function'">
                <span
                  v-bind="item.renderConfig || {}"
                  v-html="item.render({ item, row, index })"
                ></span>
              </template>
              <!-- 效验提示被遮挡请添加全局样式 -->
              <!-- .el-form-item {margin-bottom: 22px !important;} -->

              <el-form-item
                v-else-if="item.type"
                style="width: 100%"
                :prop="`${keys}.${index}.${item.prop}`"
                :rules="
                  item.rules
                    ? findConfig(item.rules, formConfig)
                    : [
                        {
                          required:
                            typeof item.required === 'function'
                              ? item.required({ row })
                              : findConfig(item.required, formConfig),
                          message:
                            item.m ||
                            item.message ||
                            `${rulesMessage[item.type]}${item.label}`,
                        },
                      ]
                "
              >
                <!-- 框架 -->
                <Frames
                  v-bind="$props"
                  :formParam="row"
                  :data="{ ...item, row, index }"
                  @changeValue="(data) => $emit('changeValue', data)"
                />
              </el-form-item>
              <!-- 自定义插槽：form标签包裹，保持页面完整性 -->
              <el-form-item
                v-else-if="item.slotForm"
                style="display: inline-block"
              >
                <slot v-bind="{ row, item, index }" :name="item.slotForm">
                  {{ item.prop ? row[item.prop] : "" }}
                </slot>
              </el-form-item>
              <!-- 自定义插槽 -->
              <slot
                v-else-if="item.slotName"
                v-bind="{ row, item, index }"
                :name="item.slotName"
              >
                {{ item.prop ? row[item.prop] : "" }}
              </slot>
            </template>
            <!-- el-table-column：本身插槽 -->
            <!-- slotData可能导致无法显示正常，删除即可 -->
            <template v-for="(value, name) in $slots" #[name]="slotData">
              <slot v-bind="slotData || {}" :name="name" />
            </template>
          </el-table-column>
          <!-- el-table：本身插槽 -->
          <!-- slotData可能导致无法显示正常，删除即可 -->
          <template v-for="(value, name) in $slots" #[name]="slotData">
            <slot v-bind="slotData || {}" :name="name" />
          </template>
        </el-table>
      </el-form-item>
      <!-- 分页 -->
      <div v-if="table && table.showFooter" class="pagination">
        <el-pagination
          :page-size="apiParam.size"
          :current-page="apiParam.current"
          :page-sizes="[10, 20, 50, 100]"
          :total="tableData.total"
          background
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        >
        </el-pagination>
      </div>
    </component>
  </div>
</template>

<script>
import Form from "./form.vue";
import Search from "./search.vue";
import Frames from "./utils/index.vue";
import defaultForm from "@/utils/defaultForm";
import { propsConfig, rulesMessage, findConfig } from "./utils/index.js";

export default {
  components: {
    Form,
    Search,
    Frames,
  },
  /** 项目列表添加行/审批居多，可使用此封装组件，分页也可 */
  emits: ["changeValue"],
  props: {
    /**
     * 是否内嵌 a-form 表单
     * is：true表示内嵌a-form标签
     * is：false则使用需要在最外层父组件使用 a-form标签包裹组件，因为在使用validate()等方法复用性高
     */
    his: { type: Boolean, default: true },
    // 表格列的配置
    table: { type: Object, default: null },
    // 列表字段，用于效验，新增删除
    keys: { type: String, default: null },
    // 接口
    apiFn: { type: Function, default: null },
    // 在父组件使用$xxRef.setFn的时候，传递一个函数替换掉getFn方法
    useFn: { type: Function, default: null },
    // 传递默认值 default: () => ({ current: 1, size: 10 })
    apiParam: { type: Object, default: null },
    // 是否内联
    inline: { type: Boolean, default: true },
    // table搜索
    form: { type: Array, default: null },
    search: { type: Array, default: null },
    // table表格label
    label: { type: String, default: null },
    // form表单是否需要label
    isLabel: { type: Boolean, default: true },
    ...propsConfig,
  },
  data() {
    return {
      loading: false,
      tableData: { data: [], total: 0 },
      rulesMessage,
      findConfig,
    };
  },
  methods: {
    /** 分页 */
    handleSizeChange(size) {
      this.apiParam.size = size;
      this.refresh();
    },
    handleCurrentChange(current) {
      this.apiParam.current = current;
      this.refresh();
    },
    /**
     * 修改apiFn父组件传递的接口，并暴露给父组件
     * 防止传递默认参数失效时使用调用setFn函数修改
     */
    setFn(newFn, params) {
      this.getFn(newFn, params);
    },
    async getFn(newFn, params = {}) {
      const { keys, table, apiFn, apiParam, formParam } = this.$props;
      const fn = apiFn || newFn;
      if (!fn) return;
      console.log(
        { ...formParam, ...apiParam, ...params },
        "列表参数：搜索“getFn”删除打印结果"
      );
      this.loading = true;
      try {
        const res = await fn({ ...formParam, ...apiParam, ...params });
        const data = res?.data || res || [];
        if (keys) {
          // 赋值默认值，防止使用 resetFields 清空无法输入
          formParam[keys] = defaultForm(table.propList, data);
          return;
        }
        this.tableData = { data, total: res?.total || 0 };
      } catch (error) {
        console.error("请求失败:", error);
      } finally {
        this.loading = false;
      }
    },
    /** 更新传递默认值 */
    updateFormParams(data) {
      Object.assign(this.apiParam, data);
    },
    /** 查询 */
    query(callback) {
      // 如果需要每次查询重置都返回第一页则打开
      // this.updateFormParams({ current: 1 });
      callback && callback();
      this.refresh();
    },
    /** 重置 */
    reset(callback) {
      for (const key in this.formParam) {
        this.formParam[key] = undefined;
      }
      callback && callback();
      // 如果不需要重置返回第一页，可以默认调用refresh方法
      this.query();
    },
    /** 刷新 */
    refresh(callback) {
      callback && callback();
      // 如果不需要重置返回第一页，可以默认调用refresh方法
      (this.$props.useFn && this.$props.useFn()) || this.getFn();
    },
  },
  created() {},
  mounted() {
    // 不建议默认refresh，获取其他接口params的时候会导致接口已经调用，参数没获取的情况
    this.getFn();
    const { formRef } = this.$refs;
    // 按需导出form表单方法
    this.validate = formRef.validate;
    this.resetFields = formRef.resetFields;
  },
};
</script>

<style scoped lang="scss">
.pagination {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
}

::v-deep.el-form--inline {
  .table {
    .el-form-item__content {
      width: 100%;
    }
  }
}

::v-deep.form-table {
  .el-form-item__content {
    margin-left: 0 !important;
  }
}
</style>
